//模拟实现Axios
const defaults = {
    timeout : 0
}

class Axios{
    constructor(defaultConfig={}) {
        this.defaults = defaultConfig;
    }
    request(configOrUrl={}, config={}){
        //如果传递的第一个参数为字符串, 则第二个参数为配置对象
        if(typeof configOrUrl === 'string'){
            //则将第一个参数的地址 , 保存到配置对象中
            config.url = configOrUrl;
        }else config = configOrUrl;
        //如果第一个参数不是字符串 , 那么第一个参数则为配置对象
        //那么将config对象直接设置为第一个参数即可


        //合并配置
        config = {
            ...this.defaults,
            ...config
        }
        //设置请求方式
        config.method = (config.method || 'get').toLowerCase();

        const {headers={}} = config;
        //拼接baseURL
        if(config.baseURL && !config.url.startsWith('http://')){
            config.url = config.baseURL + config.url;
        }
        //拼接params
        if(config.params){
            config.url = config.url + '?' + Object.keys(config.params).map(key=>key +'='+ config.params[key]).join('&');
        }

        //发送ajax请求
        const _dispatchRequest = function (){
            //返回promise对象 , 其中包含信息
            return new Promise(function (resolve, reject){
                const xhr = new XMLHttpRequest();
                //指定响应体格式
                xhr.responseType = 'json';
                xhr.open(config.method, config.url);
                //设置请求头
                for(let key in config.headers){
                    xhr.setRequestHeader(key, headers[key]);
                }

                // 当config.data的类型是对象：Content-Type:application/json
                // 当config.data的类型是字符串：Content-Type:application/x-www-form-urlencoded

                if(config.data){
                    if(typeof config.data === 'object'){
                        xhr.setRequestHeader('Content-Type', 'application/json');
                        config.data = JSON.stringify(config.data);
                    }else {
                        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                    }
                }
                xhr.send(config.data);//设置请求体
                xhr.onload = function (){
                    resolve({
                        config,
                        data : xhr.response,
                        headers : xhr.getAllResponseHeaders(),//获取响应头
                        request : xhr,
                        status : xhr.status,
                        statusText : xhr.statusText,
                    })
                }
                //处理超时情况
                xhr.ontimeout = function (){
                    reject({
                        code:"ECONNABORTED",
                        config,
                        message:"timeout of "+config.timeout+"ms exceeded",
                        name:"AxiosError",
                        request
                    })
                }
                

            })
        }

        return _dispatchRequest();
    }
}

function createInstance(defaultConfig){
    const context = new Axios(defaultConfig);
    const instance = Axios.prototype.request.bind(context);
    //instance就是request函数
    for (let key in context){
        //将context的属性复制到instance中
        instance[key] = context[key]
    }
    return instance;
}
const axios = createInstance(defaults);
//axios就是instance实例 , instance就是request函数
//所以axios就是request函数
export default axios;

//axios是一个Ajax请求库